﻿#include <iterator>
#include <set>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "server_net.h"
#include "../../3rd/libjson/LZW.h"
#include "../share/MessageDef.h"

using namespace boost::posix_time;


#include "../share/user_define.h"
#include "log.h"

void CServerNet::setKey(std::string key)
{
	mMyKey = key;
}

void CServerNet::OnInit(UShort port)
{
	net_base.set_server_addr(port);
}

boost::shared_ptr<timer> CServerNet::GetSharedPtrBySocketId(unsigned long uid)
{
	return net_base.GetSharedPtrBySocketId(uid);
}

void CServerNet::del_client(unsigned long uid)
{
	if (service_ != NULL)
	{
		service_->del_client_socket(uid);
	}
	auto it = GetSharedPtrBySocketId(uid);
	if (it != nullptr)
	{
		net_base.del_socket(it);
	}
	else
	{
		LOG_DEBUG("default","del_client client_ptr is null!");
	}
	LOG_INFO("default","del_client %d", (uint32_t)uid);
}

void CServerNet::close_client(unsigned long uid)
{
	auto it = GetSharedPtrBySocketId(uid);
	if (it != nullptr)
	{
		net_base.del_socket(it);
	}
}

CServerNet::CServerNet(IService* server, service_pump& pump) :m_pump(pump), net_base(pump, *this)
{
	service_ = server;
	mMyKey = "bloodgod20160516";
}

CServerNet::~CServerNet(void)
{
	
}


void CServerNet::NetStop()
{
	m_pump.stop_service();
}

bool CServerNet::send_by_uid(const UINT uid, std::string& msg, uint32_t msgId)
{
	return net_base.send_by_uid(uid, msg, msgId, mMyKey);
}

void CServerNet::packageStrerm(std::string& msg, int64_t uid)
{
	_safe_guard_begin;

	//	取得消息协议id
	std::string _msg_str(msg);
	uint32_t _msg_id = (uint32_t)(boost::asio::detail::socket_ops::network_to_host_long(*(ST_ASIO_HEAD_TYPE*)_msg_str.c_str()));

	std::string _msg_content_str;
	_msg_content_str.assign(_msg_str, ST_ASIO_HEAD_LEN, _msg_str.size() - ST_ASIO_HEAD_LEN);

	LOG_DEBUG("default","CServerNet recv [%d]; content : %s", _msg_id, _msg_content_str.c_str());

	//	将收到的消息增加到消息队列
	//manager_helper::AddSocketMsg(uid, _msg_id, _msg_content_str);
	if ( service_ == NULL )
	{
		LOG_ERROR("default","service is null !");
		return;
	}
	service_->AddClientMsg(uid, _msg_id, _msg_content_str);

	LOG_DEBUG("default","CServerNet::packageStrerm() -> end....");

	_safe_guard_end;
}

int CServerNet::client_msg_dispatch(std::string& msg, unsigned long uid, uint32_t msgId)
{
	return send_by_uid(uid, msg, msgId);
}

void CServerNet::broadcast_msg_to_client(uint32_t msgId, std::string& msg)
{
	net_base.broadcast_msg_to_client(msgId, msg, mMyKey);
}

bool CServerNet::is_connnected(uint32_t uid)
{
	auto it = net_base.GetSharedPtrBySocketId(uid);
	if ( it == nullptr)
	{
		return false;
	}
	return true;
}

void CNetBase::del_client(unsigned long uid)
{
	server_net_.del_client(uid);
}

void CNetBase::packageStrerm(std::string& msg, int64_t uid)
{
	server_net_.packageStrerm(msg, uid);
}

void CNetBase::broadcast_msg_to_client(uint32_t msgId, std::string& msg, const std::string& key)
{
	std::string sendString;

	//	加密与压缩
	CXOR xxor;
	xxor.Compress(msg, key);

	//	加入
	uint32_t msg_id = boost::asio::detail::socket_ops::host_to_network_long(msgId);
	sendString.reserve(ST_ASIO_HEAD_LEN);
	sendString.append((const char*)&msg_id, ST_ASIO_HEAD_LEN);
	sendString.append((char*)xxor.GetBuffer(), xxor.GetDataSize());

	LOG_DEBUG("default","broadcast_msg_to_client : %d, %d", sendString.size(), xxor.GetDataSize());

	// boost::lock_guard<boost::mutex> lock(object_can_mutex);
	for (BOOST_AUTO(iter, object_can.begin()); iter != object_can.end(); ++iter)
	{
		if (!iter->second->lowest_layer().is_open())
		{
			continue;
		}
		if (!iter->second->safe_send_msg(sendString))
		{
			LOG_WARN("default","safe_send_msg fail. msgId=0x%04X(%d) strlen=%d", msgId, msgId, msg.size());
		}
	}
}

boost::shared_ptr<timer> CNetBase::GetSharedPtrBySocketId(unsigned long uid)
{
	/*boost::mutex::scoped_lock lock(object_can_mutex);*/

	auto it = object_can.find(uid);
	if (it == object_can.end())
	{
		return nullptr;
	}
	if (!it->second->lowest_layer().is_open())
	{
		return nullptr;
	}
	return it->second;
}

bool CNetBase::send_by_uid(const UINT uid, std::string& msg, uint32_t msgId, const std::string& key)
{
	//boost::mutex::scoped_lock lock(object_can_mutex);

	auto it = object_can.find(uid);
	if (it == object_can.end())
	{
		LOG_INFO("default","uid is not find uid%d, msg:%s", uid, msg.c_str());
		return false;
	}
	if (!it->second->lowest_layer().is_open())
	{
		LOG_INFO("default","uid is not open uid%d", uid);
		return false;
	}
	std::string sendString;

	//	加密与压缩
// 	CXOR xxor;
// 	xxor.Compress(msg, key);

	//	加入
	uint32_t msg_id = boost::asio::detail::socket_ops::host_to_network_long(msgId);
	sendString.reserve(ST_ASIO_HEAD_LEN);
	sendString.append((const char*)&msg_id, ST_ASIO_HEAD_LEN);
	sendString.append(msg.c_str(), msg.size());

	if (!it->second->safe_send_msg(sendString))
	{
		LOG_WARN("default","safe_send_msg fail. msgId=0x%04X(%d) strlen=%d connext[%s]", msgId, msgId, msg.size(), msg.c_str());
	}
	else
	{
		LOG_DEBUG("default","safe_send_msg succeed. msgId=0x%04X(%d) strlen=%d connext[%s]", msgId, msgId, msg.size(), msg.c_str());
	}

	return true;
}
